from flask import request
from decorators import Transactional
from mauth.login_user_holder import LoginUserHolder
from tools import generate_id, load_model, extract_fields
from tools.db_tool import DbTool


class BaseService(object):
    """
    业务逻辑怪基类
    """

    def __init__(self, db=None, model=None):
        if db is not None:
            self.db = db
        else:
            from models import db

            self.db = db
        if model is not None:
            self.model = model
        else:
            raise Exception("model不能为空")

    def detail(self, form):
        """
        通过id获取用户信息
        :param form:
        :return:
        """
        model = self.db.session.query(self.model).get(form.id.data)
        return model

    def page(self, form):
        """
        分页查询用户列表
        :param form:
        :return:
        """
        # 可通过form.data获取所有提交参数
        # 可通过form.pageNum.data获取pageNum
        # 可通过form.pageSize.data获取pageSize
        # page=self.db.query(User).filter().paginate(form.pageNum.data, form.pageSize.data,False)
        pageNum = form.data.get("pageNum", 1)
        pageSize = form.data.get("pageSize", 10)
        page = DbTool.filter_by_custom(self.model).paginate(pageNum, pageSize, False)
        return self.model.to_page(page)

    @Transactional()
    def save(self, form):
        """
        添加用户
        :param form:
        :return:
        """
        model = self.model(**form.data)
        model.id = generate_id()
        model.createUser = LoginUserHolder.get_user_id()
        model.updateUser = LoginUserHolder.get_user_id()

        self.db.session.add(model)

    @Transactional()
    def update(self, form):
        """
        修改用户
        :param form:
        :return:
        """
        model = self.model(**form.data)

        model.updateUser = LoginUserHolder.get_user_id()

        self.db.session.query(self.model).filter_by(id=form.id.data).update(
            model.to_dict()
        )

    @Transactional()
    def remove(self, form):
        """
        删除用户
        :param form:
        :return:
        """
        self.model().remove(self.model, form.ids.data)


class LowCodeServiceUtil:
    @staticmethod
    def select(moduleName, tableName, labelKey=None, valueKey=None):
        """
        通用下拉接口
        """
        model = load_model(tableName)
        if model is None:
            return []
        data = request.get_json()
        datas = []
        includeList = []
        includeType = data.get("includeType")
        includeIds = data.get("includeIds", [])
        extFieldNames = data.get('extFieldNames', None)
        if (includeType == 1 or includeType == 2) and len(includeIds) > 0:
            includeList = (
                DbTool.filter_by_custom(model)
                .filter(getattr(model, "id").in_(includeIds))
                .all()
            )
            includeList = model.to_dict_list(includeList)
        else:
            datas = DbTool.filter_by_custom(model).all()
        rows = []
        if labelKey is None:
            labelKey = data.get("labelKey", "name")
        if valueKey is None:
            valueKey = data.get("valueKey", "id")
        for u in datas:
            dict = u.to_dict()
            rows.append({"label": dict.get(labelKey), "value": dict.get(valueKey), "ext": extract_fields(dict, extFieldNames)})
        # includeType=1，追加；includeType=2，覆盖
        if includeType == 1 and len(includeList) > 0:
            # 遍历includeList,判断是否rows是否已存在value=id的值，如果存在了，则不添加
            for include in includeList:
                if include.get(valueKey) not in [row.get("value") for row in rows]:
                    rows.append(
                        {"label": include.get(labelKey), "value": include.get(valueKey), "ext": extract_fields(include, extFieldNames)}
                    )
        elif includeType == 2 and len(includeList) > 0:
            rows = []
            for item in includeList:
                rows.append(
                    {
                        "label": item.get(labelKey),
                        "value": item.get(valueKey),
                        "ext": item.get("ext"),
                    }
                )
        return rows
